import React, { useState, useEffect, useRef } from 'react';

/**
 * 防重渲染高阶组件
 * @param {React.Component} Component - 要包装的组件
 * @param {Function} shouldUpdate - 自定义更新条件函数
 */
export const withMemoization = (Component, shouldUpdate = (prevProps, nextProps) => true) => {
  return React.memo(Component, (prevProps, nextProps) => {
    return !shouldUpdate(prevProps, nextProps);
  });
};

/**
 * 使用requestIdleCallback的渲染调度
 * @param {React.Component} Component - 要优化的组件
 */
export const withIdleRendering = (Component, placeHolder = null) => {
  return function IdleRenderedComponent(props) {
    const [shouldRender, setShouldRender] = useState(false);

    useEffect(() => {
      if ('requestIdleCallback' in window) {
        const handle = requestIdleCallback(() => {
          setShouldRender(true);
        });
        return () => cancelIdleCallback(handle);
      }
      setShouldRender(true); // 浏览器不支持则直接渲染
    }, []);

    return shouldRender ? <Component {...props} /> : placeHolder;
  };
};

/**
 * 按帧分批渲染的Hook
 * @param {Array} items - 要渲染的数据项
 * @param {number} batchSize - 每批渲染的数量
 */
export const useIncrementalRendering = (items, batchSize = 5) => {
  const [visibleItems, setVisibleItems] = useState([]);
  const frameRef = useRef(null);

  useEffect(() => {
    let currentIndex = 0;

    const renderBatch = () => {
      const nextIndex = Math.min(currentIndex + batchSize, items.length);
      setVisibleItems(items.slice(0, nextIndex));
      currentIndex = nextIndex;

      if (currentIndex < items.length) {
        frameRef.current = requestAnimationFrame(renderBatch);
      }
    };

    frameRef.current = requestAnimationFrame(renderBatch);
    return () => cancelAnimationFrame(frameRef.current);
  }, [items, batchSize]);

  return visibleItems;
};

/**
 * 避免布局抖动的节流渲染Hook
 */
export const useThrottledRender = (deps = [], interval = 32) => {
  const [_, forceUpdate] = useState({});
  const lastUpdateRef = useRef(0);

  return useEffect(() => {
    const now = Date.now();
    if (now - lastUpdateRef.current >= interval) {
      lastUpdateRef.current = now;
      forceUpdate({});
    }
  }, deps);
};
